package com.binguo.api.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.binguo.api.alipay.util.PriceUtil;
import com.binguo.api.response.api.BaseChargeResp;
import com.binguo.api.response.api.BaseUserInfo;
import com.binguo.api.schedule.DataLoadService;
import com.binguo.api.service.api.ShopApiInterface;
import com.binguo.common.exception.ServiceException;
import com.binguo.common.util.Base64Util;
import com.binguo.common.util.UploadExcelService;
import com.binguo.helper.FaceHelperV3;
import com.binguo.model.api.dto.OrderDTO;
import com.binguo.model.api.dto.OrderItemDTO;
import com.binguo.model.mapper.FaceMapper;
import com.binguo.model.mapper.ProductMapper;
import com.binguo.model.mapper.ShopMapper;
import com.binguo.model.model.*;
import com.binguo.model.repository.*;
import com.binguo.service.CustomerService;
import com.binguo.service.ProductService;
import com.binguo.thirdPay.ruijingPay.RuiJingPayForm;
import com.binguo.thirdPay.ruijingPay.RuiJingShopService;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Condition;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * @author yuritian
 * @Title: RuiJingService
 * @ProjectName binguoDevelop
 * @Description: TODO
 * @date 2020/3/2015:07
 */
@Service
public class RuiJingService implements ShopApiInterface, InitializingBean {
    private static Logger logger = LoggerFactory.getLogger(RuiJingService.class);

    private List<Integer> shopIdList;
    private Map<Integer, String> shopMap;

    @Resource
    private ShopMapper shopMapper;

    @Resource
    private RedisLockService redisLockService;

    @Resource
    private RuiJingShopService ruiJingShopService;

    @Resource
    private ProductCategoryRepository productCategoryRepository;

    @Resource
    private ProductService productService;

    @Resource
    private ProductRepository productRepository;

    @Resource
    private ProductMapper productMapper;

    @Autowired
    private CashierDeskRepository cashierDeskRepository;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private CustomerRepository customerRepository;

    @Resource
    private FaceMapper faceMapper;

    @Resource
    private FileUploadRepository fileUploadRepository;

    @Resource
    private UploadExcelService uploadExcelService;

    @Resource
    private ThirdFaceUpdateRepository thirdFaceUpdateRepository;

    @Override
    public BaseChargeResp payPreHandler(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp payPostHandler(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseUserInfo getUserInfo(String cardNo) {
        return null;
    }

    @Override
    public BaseChargeResp getProductList() {
        return null;
    }

    public BaseChargeResp getProductList(Integer deskId) {
        Map<Integer,Integer> categoryMap = new HashMap<>();
        CashierDesk cashierDesk = cashierDeskRepository.findById(deskId);
        Integer branchId = cashierDesk.getBranchid();
        String deviceId = cashierDesk.getCcode();
        Integer shopId = cashierDesk.getShopid();
        productMapper.deleteProduct(branchId);
        JSONObject categoryList = ruiJingShopService.ruiJingDishTypeSync(deviceId);
        if (categoryList == null){
            return null;
        }
        JSONObject data = categoryList.getJSONObject("data");
        JSONArray itemClassList = data.getJSONArray("list");
        for (int i = 0; i < itemClassList.size(); i++) {
            JSONObject itemData = itemClassList.getJSONObject(i);
            String code = itemData.getString("id");
            Condition condition = new Condition(ProductCategory.class);
            condition.or().andEqualTo("shopWebId",code);
            List<ProductCategory> productCategoryList = productCategoryRepository.findByCondition(condition);
            if (null == productCategoryList || productCategoryList.size() == 0) {
                ProductCategory category = new ProductCategory();
                category.setDeleted(false);
                category.setName(itemData.getString("name"));
                category.setShopid(shopId);
                category.setShopWebId(code);
                category.setType(new Byte("1"));
                category.setParentid(0);
                productCategoryRepository.save(category);
                categoryMap.put(Integer.valueOf(code),category.getId());
            } else {
                ProductCategory category = productCategoryList.get(0);
                category.setName(itemData.getString("name"));
                category.setDeleted(false);
                productCategoryRepository.update(category);
                categoryMap.put(Integer.valueOf(code),category.getId());
            }
        }
        JSONObject productList = ruiJingShopService.ruiJingDishSync(deviceId, 0, 10);
        if (productList == null){
            return null;
        }
        data = productList.getJSONObject("data");
        Integer total = data.getInteger("total");
        Integer size = (total / 10) + 1;
        for (int i = 1; i <= size; i++) {
            if (i != 1) {
                productList = ruiJingShopService.ruiJingDishSync(deviceId, (i - 1) * 10, 10);
                if (productList == null){
                    return null;
                }
                data = productList.getJSONObject("data");
            }
            JSONArray productArray = data.getJSONArray("list");
            for (int j = 0; j < productArray.size(); j++) {
                JSONObject itemData = productArray.getJSONObject(j);
                String searchId = shopId + "_" + itemData.getInteger("dishid");
                Product product = productService.getRuiJingProductBySearchCode(shopId, searchId);
                if (product == null) {
                    product = new Product();
                    product.setName(itemData.getString("name"));
                    product.setSearchcode(searchId);
                    product.setMinorcategoryid(categoryMap.get(itemData.getInteger("type")));
                    product.setPrice(PriceUtil.getRealPrice(itemData.getFloat("price").toString()));
                    product.setDeleted(false);
                    product.setShopid(shopId);
                    product.setStoreid(branchId);
                    product.setStatus(new Byte("1"));
                    productRepository.save(product);
                } else {
                    product.setName(itemData.getString("name"));
                    product.setMinorcategoryid(categoryMap.get(itemData.getInteger("type")));
                    product.setPrice(PriceUtil.getRealPrice(itemData.getFloat("price").toString()));
                    product.setDeleted(false);
                    product.setStatus(new Byte("1"));
                    productRepository.update(product);
                }
            }
        }
        BaseChargeResp resp = new BaseChargeResp();
        resp.setCode(200);
        return resp;
    }

    @Override
    public BaseChargeResp cardPay(OrderDTO orderDTO) {
        BaseChargeResp resp = new BaseChargeResp();
        String code = orderDTO.getCardNo();
        Integer deskId = orderDTO.getCashierDeskId();
        CashierDesk desk = cashierDeskRepository.findById(deskId);
        String deviceId = desk.getCcode();
        List<RuiJingPayForm> payFormList = getRuiJingPayFormList(orderDTO.getItems());
        if (payFormList == null){
            throw new ServiceException("商品ID异常");
        }
        JSONObject result = ruiJingShopService.ruiJingOrder(deviceId,orderDTO.getUserId(),1,code,payFormList);
        Integer resultCode = result.getInteger("rst");
        if (!resultCode.equals(200)) {
            throw new ServiceException(result.getString("msg"));
        }else {
            resp.setCode(200);
            resp.setData(result);
            return resp;
        }
    }

    @Override
    public BaseChargeResp wxPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp aliPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp facePay(OrderDTO orderDTO) {
        BaseChargeResp resp = new BaseChargeResp();
        Integer customerId = orderDTO.getCustomerId();
        Customer customer = customerRepository.findById(customerId);
        String code = customer.getShopCustomerid().split("_")[1];
        Integer deskId = orderDTO.getCashierDeskId();
        CashierDesk desk = cashierDeskRepository.findById(deskId);
        String deviceId = desk.getCcode();
        List<RuiJingPayForm> payFormList = getRuiJingPayFormList(orderDTO.getItems());
        if (payFormList == null){
            throw new ServiceException("商品ID异常");
        }
        JSONObject result = ruiJingShopService.ruiJingOrder(deviceId,orderDTO.getUserId(),3,code,payFormList);
        Integer resultCode = result.getInteger("rst");
        if (!resultCode.equals(200)) {
            throw new ServiceException(result.getString("msg"));
        }else {
            resp.setCode(200);
            resp.setData(result);
            return resp;
        }
    }

    @Override
    public BaseChargeResp cashPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp qrCodePay(OrderDTO orderDTO) {
        BaseChargeResp resp = new BaseChargeResp();
        String code = orderDTO.getAuthCode();
        Integer deskId = orderDTO.getCashierDeskId();
        CashierDesk desk = cashierDeskRepository.findById(deskId);
        String deviceId = desk.getCcode();
        List<RuiJingPayForm> payFormList = getRuiJingPayFormList(orderDTO.getItems());
        if (payFormList == null) {
            throw new ServiceException("商品ID异常");
        }
        JSONObject result = ruiJingShopService.ruiJingOrder(deviceId, orderDTO.getUserId(), 2, code, payFormList);
        Integer resultCode = result.getInteger("rst");
        if (!resultCode.equals(200)) {
            throw new ServiceException(result.getString("msg"));
        }else {
            resp.setCode(200);
            resp.setData(result);
            return resp;
        }
    }

    public String updateFace(Integer deskId,
                             Integer userId) {

        CashierDesk cashierDesk = cashierDeskRepository.findById(deskId);
        Integer shopId = cashierDesk.getShopid();
        String deviceId = cashierDesk.getCcode();
        Integer branchId = cashierDesk.getBranchid();

        Condition condition = new Condition(FileUpload.class);
        condition.or().andEqualTo("shopId", shopId)
                .andEqualTo("branchId", branchId)
                .andEqualTo("uploadType", 4)
                .andEqualTo("result", 0);
        List<FileUpload> fileUploadList = fileUploadRepository.findByCondition(condition);

        if (fileUploadList != null && fileUploadList.size() > 0) {
            return "有正在处理的人脸批量更新操作,请稍后再试";
        } else {
            FileUpload fileUpload = new FileUpload();
            fileUpload.setCreateId(userId);
            fileUpload.setCreateTime(new Date());
            fileUpload.setBranchId(branchId);
            fileUpload.setShopId(shopId);
            fileUpload.setResult(0);
            fileUpload.setUploadType(4);
            fileUploadRepository.save(fileUpload);
            CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(() -> {
                try {
                    Integer offset;
                    ThirdFaceUpdate faceUpdate;

                    Condition thirdFaceCondition = new Condition(ThirdFaceUpdate.class);
                    thirdFaceCondition.or().andEqualTo("deskId",deskId);
                    List<ThirdFaceUpdate> faceUpdateList = thirdFaceUpdateRepository.findByCondition(thirdFaceCondition);
                    if (null == faceUpdateList || faceUpdateList.size() == 0){
                        offset = 0;
                        faceUpdate = new ThirdFaceUpdate();
                        faceUpdate.setBranchId(branchId);
                        faceUpdate.setDeskId(deskId);
                        faceUpdate.setShopId(shopId);
                        faceUpdate.setFaceId("0");
                        faceUpdate.setCreateId(deskId);
                        faceUpdate.setCreateTime(new Date());
                        faceUpdate.setUpdateId(deskId);
                        faceUpdate.setUpdateTime(new Date());
                        thirdFaceUpdateRepository.save(faceUpdate);
                    }else {
                        faceUpdate = faceUpdateList.get(0);
                        offset = Integer.valueOf(faceUpdate.getFaceId());
                    }

                    JSONArray failArray = new JSONArray();

                    JSONObject faceJsonObject = ruiJingShopService.ruiJingFace(deviceId, offset, 10);
                    if (faceJsonObject == null) {
                        return null;
                    }
                    Integer total = faceJsonObject.getInteger("total");
                    JSONArray faceList = faceJsonObject.getJSONArray("list");
                    Integer size = (total / 10) + 1;
                    Integer bigNum = offset;
                    for (int i = 1; i <= size; i++) {
                        if (i != 1) {
                            faceJsonObject = ruiJingShopService.ruiJingFace(deviceId, bigNum, 10);
                            if (faceJsonObject == null) {
                                return null;
                            }
                            faceList = faceJsonObject.getJSONArray("list");
                        }
                        for (int j = 0; j < faceList.size(); j++) {
                            JSONObject ruiJingCustomerObject = faceList.getJSONObject(j);
                            Integer mid = ruiJingCustomerObject.getInteger("mid");
                            Integer id = ruiJingCustomerObject.getInteger("id");
                            bigNum = id;
                            Integer type = ruiJingCustomerObject.getInteger("type");
                            String name = ruiJingCustomerObject.getString("name");
                            String faceUrl = ruiJingCustomerObject.getString("hash");
                            String shopCustomerId = shopId + "_" + mid;
                            Customer customer = customerService.getCustomerByShopCustomerId(shopCustomerId);
                            if (customer == null) {
                                if (!type.equals(2)) {
                                    customer = new Customer();
                                    customer.setName(name);
                                    customer.setShopCustomerid(shopCustomerId);
                                    customerRepository.save(customer);
                                    String persionId = shopId + "_" + customer.getId();
                                    boolean faceResult = createOrAddFace(shopId, persionId, faceUrl, customer.getId(), 1);
                                    if (!faceResult) {
                                        JSONObject failObject = new JSONObject();
                                        faceJsonObject.put("id", mid);
                                        faceJsonObject.put("msg", name + mid + "创建人脸失败");
                                        failArray.add(failObject);
                                    }
                                }
                            } else {
                                customer.setName(name);
                                customerRepository.update(customer);
                                String persionId = shopId + "_" + customer.getId();
                                if (!type.equals(2)) {
                                    Condition tempFaceExample = new Condition(Face.class);
                                    tempFaceExample.or().andEqualTo("persionid", persionId);
                                    List<Face> tempFaceList = faceMapper.selectByCondition(tempFaceExample);
                                    Boolean isFaceIn = true;
                                    if (null != tempFaceList && tempFaceList.size() > 0) {
                                        for (Face face : tempFaceList) {
                                            if (face.getFaceurl().equals(faceUrl)) {
                                                isFaceIn = false;
                                                break;
                                            }
                                        }
                                        if (isFaceIn) {
                                            boolean faceResult = createOrAddFace(shopId, persionId, faceUrl, customer.getId(), 2);
                                            if (!faceResult) {
                                                JSONObject failObject = new JSONObject();
                                                faceJsonObject.put("id", mid);
                                                faceJsonObject.put("msg", name + mid + "更新人脸失败");
                                                failArray.add(failObject);
                                            }
                                        }
                                    } else {
                                        boolean faceResult = createOrAddFace(shopId, persionId, faceUrl, customer.getId(), 1);
                                        if (!faceResult) {
                                            JSONObject failObject = new JSONObject();
                                            faceJsonObject.put("id", mid);
                                            faceJsonObject.put("msg", name + mid + "创建人脸失败");
                                            failArray.add(failObject);
                                        }
                                    }
                                } else {
                                    FaceHelperV3.deletePersonFromShop(shopId.toString(), persionId);
                                }
                            }
                        }
                    }

                    Workbook workBook = new XSSFWorkbook();
                    Sheet sheet = workBook.createSheet("处理结果");
                    sheet.setDefaultColumnWidth(20);
                    Row row = sheet.createRow(0);
                    Cell cell = row.createCell(0);
                    cell.setCellValue("瑞景Id");
                    cell = row.createCell(1);
                    cell.setCellValue("错误信息");
                    if (failArray.size() > 0) {
                        for (int i = 0; i < failArray.size(); i++) {
                            JSONObject object = faceList.getJSONObject(i);
                            row = sheet.createRow(i + 1);
                            cell = row.createCell(0);
                            cell.setCellValue(object.getInteger("mid"));
                            cell = row.createCell(1);
                            cell.setCellValue(object.getString("msg"));
                        }
                    } else {
                        row = sheet.createRow(1);
                        cell = row.createCell(0);
                        cell.setCellValue("没有异常");
                    }
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    workBook.write(bos);
                    byte[] barray = bos.toByteArray();
                    String base64 = Base64Util.encode(barray);
                    String uploadResult = uploadExcelService.uploadExcel(shopId, base64, "xlsx");
                    fileUpload.setUpdateTime(new Date());
                    fileUpload.setResult(1);
                    fileUpload.setNewFile(uploadResult);
                    fileUploadRepository.update(fileUpload);
                    faceUpdate.setFaceId(bigNum.toString());
                    faceUpdate.setUpdateTime(new Date());
                    faceUpdate.setUpdateId(deskId);
                    thirdFaceUpdateRepository.update(faceUpdate);
                } catch (Throwable e) {
                    fileUpload.setUpdateTime(new Date());
                    fileUpload.setResult(2);
                    fileUploadRepository.update(fileUpload);
                    e.printStackTrace();
                }
                return true;
            });
            return "正在处理人脸批量更新操作";
        }
    }

    private boolean createOrAddFace(Integer shopId,
                                    String persionId,
                                    String faceUrl,
                                    Integer customerId,
                                    Integer type) {
        String tempFaceId;
        if (type.equals(2)) {
            FaceHelperV3.deletePerson(persionId);
        }
        tempFaceId = FaceHelperV3.createPerson(shopId.toString(), persionId, faceUrl);

        if (tempFaceId == null) {
            return false;
        } else {
            Face temp = new Face();
            temp.setFaceid(tempFaceId);
            temp.setCustomerId(customerId);
            temp.setFaceurl(faceUrl);
            temp.setPersionid(persionId);
            faceMapper.insertSelective(temp);
            return true;
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Condition condition = new Condition(Shop.class);
        condition.or().andEqualTo("apiServiceClassName", "RuiJingService");
        List<Shop> shopList = shopMapper.selectByCondition(condition);

        shopMap = new HashMap<>();
        shopIdList = new ArrayList<>();

        if (shopList != null && shopList.size() > 0) {
            for (Shop shop : shopList) {
                shopMap.put(shop.getId(), shop.getName());
                shopIdList.add(shop.getId());
            }
        }
    }

    public List<RuiJingPayForm> getRuiJingPayFormList(List<OrderItemDTO> itemList){
        List<RuiJingPayForm> payFormList = new ArrayList<>();
        for (OrderItemDTO itemDTO : itemList){
            Product product;
            RuiJingPayForm payForm = new RuiJingPayForm();
            payForm.setNum(itemDTO.getQuantity());
            if (DataLoadService.productMap != null) {
                product = productRepository.findById(itemDTO.getProductId());
            }else {
                product = productRepository.findById(itemDTO.getProductId());
            }
            if (product == null){
                logger.error("商品ID异常,异常ID为:" + itemDTO.getProductId());
                return null;
            }
            payForm.setDishid(product.getSearchcode().split("_")[1]);
            payFormList.add(payForm);
        }
        return payFormList;
    }
}
